package Threads;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;

import javax.lang.model.util.Elements;

import Structs.Member;

import Debug.Debug;
import Enums.Type_log;
import Enums.Type_rsp;
import Interfaces.C_interface;
import Structs.Log;
import Structs.Msg_broad;
import Structs.Msg_rsp;

public class S_Broadcast implements Runnable{
	private Hashtable<String,Object> Loged;
	private BlockingQueue<Msg_broad> requests;
	private BlockingDeque<Log> log;

	public S_Broadcast(Hashtable<String,Object>Loged,BlockingQueue<Msg_broad> requests, BlockingDeque<Log>log){
		this.Loged = Loged;
		this.requests = requests;
		this.log = log;
		new Thread(this).start();
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		Msg_broad ToSend;
		Enumeration<Object> ToWho;
		Iterator<Log> login;
		String replypastnotific;
		Log i;
		
		Object tmp;
		String msgbroadtask = "";
		
		boolean canreplypast;
		
		C_interface rmi;
		
		C_interface rmi_tmp;
		ObjectOutputStream tcp_tmp;
		
		
		while(true){
			try {
				ToSend = requests.take();
				
				if(new Debug().isDebug())
					System.out.println("recieved work");
				
				switch(ToSend.getType()){
				case Login:
					if(new Debug().isDebug())
						System.out.println("sending login");
					
					ToSend.getTcp().writeObject(ToSend.getTcp_msg());
					canreplypast = false;
					if(!log.isEmpty()){
						login = ((LinkedBlockingDeque<Log>)log).descendingIterator();

						if(ToSend.getFrom()!=null){
							replypastnotific="";
							while(login.hasNext()){
								i=login.next();
								if((i.getType()==Type_log.Logout || i.getType()==Type_log.Register)  && i.getMessage().equals(ToSend.getFrom().getUser())){
									canreplypast = true;
									break;
								}
								if(i.getType()==Type_log.NewTask || i.getType()==Type_log.EditTask || i.getType()==Type_log.FinishTask){
									replypastnotific=replypastnotific+'\n'+i.getMessage();
								}
							}
							if(canreplypast){
								ToSend.getTcp().writeObject(new Msg_rsp(Type_rsp.ListTasks, replypastnotific, 0));
							}
						}
					}
					break;
				case Logout:
					ToSend.getTcp().writeObject(ToSend.getTcp_msg());
					break;
				case Register:
					ToSend.getTcp().writeObject(ToSend.getTcp_msg());
					break;
				case ListTasks:
					if(ToSend.getTcp()!=null){
						ToSend.getTcp().writeObject(ToSend.getTcp_msg());
					} else {
						rmi = (C_interface) Loged.get(ToSend.getFrom().getUser());
						rmi.PrintOnClient(ToSend.getTcp_msg().getName());
					}
				break;
				case NewTask:
					msgbroadtask = "New";
				case EditTask:
					if(!msgbroadtask.equals(""))
						msgbroadtask = "Edit";
				case FinishTask:
					if(!msgbroadtask.equals(""))
						msgbroadtask = "Finish";
					if(new Debug().isDebug())
						System.out.println("Broadcasting");
					if(ToSend.getTcp()==null){
						if(!Loged.isEmpty()){
							Member tmp1 = ToSend.getFrom();
							if(Loged.containsKey(ToSend.getFrom().getUser())){
								rmi = (C_interface) Loged.get(ToSend.getFrom().getUser());
							}
							else{
								System.out.println("bode!!!");
								rmi=null;
							}
						} else {
							rmi = null;
						}
						
						ToWho=Loged.elements();
						while(ToWho.hasMoreElements()){
							tmp=ToWho.nextElement();
							System.out.println(tmp.getClass());
							if(tmp.getClass()!=ObjectOutputStream.class){
								if(((C_interface) tmp).equals(rmi)){
									System.out.println(ToSend.getTcp_msg().getName());
									rmi.PrintOnClient(ToSend.getTcp_msg().getName());
								}else {
									((C_interface) tmp).PrintOnClient("Task "+ToSend.getTcp_msg().getId()+
												msgbroadtask);	
								}
							}else{
								((ObjectOutputStream) tmp).writeObject(
										new Msg_rsp(ToSend.getType(),"Task "+ToSend.getTcp_msg().getId()+
												msgbroadtask,0));
							}
						}
					}else {
						ToWho=Loged.elements();
						ToSend.getTcp().writeObject(ToSend.getTcp_msg());
						while(ToWho.hasMoreElements()){
							tmp=ToWho.nextElement();
							if(tmp.getClass()==C_interface.class){
								((C_interface) tmp).PrintOnClient("Task "+ToSend.getTcp_msg().getId()+
										msgbroadtask);
							}else{
								if(!(((ObjectOutputStream) tmp).equals(ToSend.getTcp()))){
									((ObjectOutputStream) tmp).writeObject(
										new Msg_rsp(ToSend.getType(),"Task "+ToSend.getTcp_msg().getId()+
												msgbroadtask,0));
								}
							}
						}
					}
					msgbroadtask = "";
					break;
				case Error:
					if(ToSend.getTcp()!=null){
						ToSend.getTcp().writeObject(ToSend.getTcp_msg());
					} else {
						rmi = (C_interface) Loged.get(ToSend.getFrom().getUser());
						rmi.PrintOnClient(ToSend.getTcp_msg().getName());
					}
					break;
				case Ack:
					if(new Debug().isDebug())
						System.out.println("sending ack");
					ToSend.getTcp().writeObject(ToSend.getTcp_msg());
				}

				
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				if(new Debug().isDebug())
					System.out.println("Interrupted error from broadcast");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
	}

}